#include "discoveryclient.h"
#include <QJsonArray>
#include <QDebug>
#include <QRandomGenerator>
#include <QCoreApplication>
#include <QThread>
#include <QEventLoop>
#include <QTimer>
#include <QMetaObject>
#include <cstring>
#include <memory>

namespace Discovery {

const QString DiscoveryClient::MULTICAST_ADDR = "239.1.2.3";
const int DiscoveryClient::DISCOVERY_PORT = 53702;

DiscoveryClient::DiscoveryClient(QObject *parent)
    : QObject(parent)
    , m_loop(nullptr)
    , m_isRunning(false)
    , m_timeoutSeconds(5)
    , m_retryCount(0)
    , m_sentCount(0)
    , m_nextCallbackId(1)
    , m_eventLoop(nullptr)
{
    // 初始化LibUV
    m_loop = new uv_loop_t;
    int r = uv_loop_init(m_loop);
    if (r != 0) {
        qCritical() << "Failed to initialize uv loop:" << uv_strerror(r);
        delete m_loop;
        m_loop = nullptr;
        return;
    }
    m_loop->data = this;
    
    // 初始化UDP句柄
    memset(&m_udpHandle, 0, sizeof(m_udpHandle));
    memset(&m_retryTimer, 0, sizeof(m_retryTimer));
    memset(&m_sendAddr, 0, sizeof(m_sendAddr));
}

DiscoveryClient::~DiscoveryClient()
{
    stop();
    if (m_loop) {
        int r = uv_loop_close(m_loop);
        if (r == UV_EBUSY) {
            qDebug() << "Loop has active handles, attempting walk and close";
            uv_walk(m_loop, walkCallback, nullptr);
            uv_run(m_loop, UV_RUN_NOWAIT);
            r = uv_loop_close(m_loop);
        }
        if (r != 0) {
            qWarning() << "Failed to close uv loop:" << uv_strerror(r);
        }
        delete m_loop;
        m_loop = nullptr;
    }
}

DiscoveryClient& DiscoveryClient::instance()
{
    static DiscoveryClient instance;
    return instance;
}

bool DiscoveryClient::start(int timeoutSeconds, const QString& networkInterface, int retryCount)
{
    if (m_isRunning.load()) {
        qDebug() << "Discovery client already running";
        return true;
    }

    if (!m_loop) {
        qCritical() << "Cannot start, uv loop is not initialized";
        return false;
    }

    m_timeoutSeconds = timeoutSeconds;
    m_networkInterface = networkInterface;
    m_retryCount = retryCount;
    m_startTime = std::chrono::steady_clock::now();
    m_sentCount = 0;

    // 清空本轮扫描中已发现的设备 IP 集合
    m_seenDeviceIps.clear();
    
    qDebug() << "=== Starting DiscoveryClient with LibUV ===";
    qDebug() << "Timeout:" << m_timeoutSeconds << "seconds";
    qDebug() << "Multicast address:" << MULTICAST_ADDR << ":" << DISCOVERY_PORT;
    if (m_networkInterface.isEmpty()) {
        qCritical() << "Network interface is required but not provided";
        return false;
    }
    qDebug() << "Network interface:" << m_networkInterface;

    // 初始化UDP发送地址
    uv_ip4_addr(MULTICAST_ADDR.toUtf8().constData(), DISCOVERY_PORT, &m_sendAddr);

    // 初始化UDP句柄
    int r = uv_udp_init(m_loop, &m_udpHandle);
    if (r != 0) {
        qCritical() << "Failed to initialize UDP handle:" << uv_strerror(r);
        return false;
    }
    m_udpHandle.data = this;

    struct sockaddr_in recv_addr;
    // 绑定到指定的网络接口
    const char* bindAddr = m_networkInterface.toUtf8().constData();
    uv_ip4_addr(bindAddr, 0, &recv_addr);

    // 绑定UDP句柄
    r = uv_udp_bind(&m_udpHandle, (const struct sockaddr *)&recv_addr, UV_UDP_REUSEADDR);
    if (r != 0) {
        qCritical() << "Failed to bind UDP handle to" << bindAddr << ":" << uv_strerror(r);
        return false;
    }

    // 获取并显示绑定的本地端口信息
    struct sockaddr_in bound_addr;
    int addr_len = sizeof(bound_addr);
    r = uv_udp_getsockname(&m_udpHandle, (struct sockaddr*)&bound_addr, &addr_len);
    if (r == 0) {
        char bound_ip[17] = {0};
        uv_ip4_name(&bound_addr, bound_ip, 16);
        int bound_port = ntohs(bound_addr.sin_port);
        qDebug() << "UDP socket bound to local address:" << bound_ip << ":" << bound_port;
    } else {
        qWarning() << "Failed to get socket name:" << uv_strerror(r);
    }

    // 开始接收UDP消息
    r = uv_udp_recv_start(&m_udpHandle, onAllocBuffer, onUdpRecv);
    if (r != 0) {
        qCritical() << "Failed to start UDP receive:" << uv_strerror(r);
        uv_close((uv_handle_t *)&m_udpHandle, nullptr);
        return false;
    }

    // 加入多播组 - 这是关键步骤！在指定网络接口加入多播组
    const char* multicastInterface = m_networkInterface.toUtf8().constData();
    r = uv_udp_set_membership(&m_udpHandle, MULTICAST_ADDR.toUtf8().constData(), 
                              multicastInterface, UV_JOIN_GROUP);
    if (r != 0) {
        qWarning() << "Failed to join multicast group:" << MULTICAST_ADDR 
                   << "on interface:" << multicastInterface
                   << "Error:" << uv_strerror(r);
        qWarning() << "This may prevent receiving multicast responses";
        // 不返回false，因为发送仍然可能工作
    } else {
        qDebug() << "Successfully joined multicast group:" << MULTICAST_ADDR
                 << "on interface:" << multicastInterface;
    }
    
    // 设置多播接口（用于发送）
    r = uv_udp_set_multicast_interface(&m_udpHandle, m_networkInterface.toUtf8().constData());
    if (r != 0) {
        qWarning() << "Failed to set multicast interface to" << m_networkInterface << ":" << uv_strerror(r);
    } else {
        qDebug() << "Multicast interface set to:" << m_networkInterface;
    }

    // 设置多播TTL
    r = uv_udp_set_ttl(&m_udpHandle, 1);
    if (r != 0) {
        qWarning() << "Failed to set multicast TTL:" << uv_strerror(r);
    } else {
        qDebug() << "Multicast TTL set to 1";
    }

    // 启用多播环回（用于测试）
    r = uv_udp_set_multicast_loop(&m_udpHandle, 1);
    if (r != 0) {
        qWarning() << "Failed to enable multicast loopback:" << uv_strerror(r);
    } else {
        qDebug() << "Multicast loopback enabled for testing";
    }

    m_isRunning.store(true);

    // 在单独的线程中启动libuv事件循环
    m_loopThread = std::thread(&DiscoveryClient::runLoop, this);

    // 直接发送首次 discovery 请求
    sendDiscoveryRequest();

    // 如果需要重试，则启动一个定时器周期性重发
    if (m_retryCount > 0) {
        int rTimer = uv_timer_init(m_loop, &m_retryTimer);
        if (rTimer != 0) {
            qWarning() << "Failed to init retry timer:" << uv_strerror(rTimer);
        } else {
            m_retryTimer.data = this;
            // 每 1000ms 触发一次，直到满足发送次数或到达总超时
            rTimer = uv_timer_start(&m_retryTimer,
                                    [](uv_timer_t* handle) {
                                        auto* self = static_cast<DiscoveryClient*>(handle->data);
                                        if (!self) return;

                                        // 已经停止或 loop 即将退出
                                        if (!self->m_isRunning.load()) {
                                            uv_timer_stop(handle);
                                            uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
                                            return;
                                        }

                                        auto now = std::chrono::steady_clock::now();
                                        auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - self->m_startTime).count();
                                        if (elapsed >= self->m_timeoutSeconds) {
                                            // 超时后不再发送，计时器收尾动作交给 stopLoopHandles
                                            uv_timer_stop(handle);
                                            uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
                                            return;
                                        }

                                        // 已发送次数达到上限：1 + retryCount
                                        if (self->m_sentCount >= (1 + self->m_retryCount)) {
                                            uv_timer_stop(handle);
                                            uv_close(reinterpret_cast<uv_handle_t*>(handle), nullptr);
                                            return;
                                        }

                                        self->sendDiscoveryRequest();
                                    },
                                    1000, 1000);

            if (rTimer != 0) {
                qWarning() << "Failed to start retry timer:" << uv_strerror(rTimer);
            } else {
                qDebug() << "Discovery retry timer started with retryCount =" << m_retryCount;
            }
        }
    }

    qDebug() << "Discovery client started, will timeout in" << m_timeoutSeconds << "seconds";
    return true;
}

void DiscoveryClient::stop()
{
    if (!m_isRunning.load()) {
        return;
    }

    qDebug() << "=== Stopping DiscoveryClient ===" ;

    m_isRunning.store(false);

    if (m_loop) {
        // 使用uv_async_send来唤醒被阻塞的循环
        uv_async_t *async = new uv_async_t;
        uv_async_init(m_loop, async, [](uv_async_t *handle) {
            uv_close((uv_handle_t *)handle, 
                     [](uv_handle_t *h) { delete (uv_async_t *)h; });
        });
        uv_async_send(async);
    }

    // 等待循环线程结束
    if (m_loopThread.joinable()) {
        m_loopThread.join();
    }

    // 如果有事件循环在运行，退出它
    if (m_eventLoop && m_eventLoop->isRunning()) {
        m_eventLoop->quit();
    }

    qDebug() << "Discovery client stopped";
    QMetaObject::invokeMethod(this, [this]() {
        qDebug() << "=== Emitting discoveryFinished signal in main thread (stop) ===";
        emit discoveryFinished();
    }, Qt::QueuedConnection);
}

QList<DeviceDiscoveryInfo> DiscoveryClient::searchDevicesSync(int timeoutSeconds, const QString& networkInterface)
{
    QList<DeviceDiscoveryInfo> foundDevices;
    
    if (m_isRunning) {
        qWarning() << "Discovery client is already running, cannot perform sync search";
        return foundDevices;
    }
    
    // 创建临时事件循环
    QEventLoop eventLoop;
    m_eventLoop = &eventLoop;
    
    // 连接信号以收集发现的设备
    auto deviceFoundConnection = connect(this, &DiscoveryClient::deviceFound, 
        [&foundDevices](const DeviceDiscoveryInfo& device) {
            foundDevices.append(device);
        });
    
    // 连接完成信号以退出事件循环
    auto finishedConnection = connect(this, &DiscoveryClient::discoveryFinished, 
        &eventLoop, &QEventLoop::quit);
    
    // 启动搜索
    if (!start(timeoutSeconds, networkInterface)) {
        disconnect(deviceFoundConnection);
        disconnect(finishedConnection);
        m_eventLoop = nullptr;
        return foundDevices;
    }
    
    // 运行事件循环直到搜索完成或超时
    eventLoop.exec();
    
    // 清理
    disconnect(deviceFoundConnection);
    disconnect(finishedConnection);
    m_eventLoop = nullptr;
    
    qDebug() << "Sync search completed, found" << foundDevices.size() << "devices";
    return foundDevices;
}

int DiscoveryClient::registerCallback(const DeviceFoundCallback& callback)
{
    if (!callback) {
        qWarning() << "Cannot register null callback";
        return -1;
    }

    int handle = m_nextCallbackId++;
    m_callbacks[handle] = callback;
    qDebug() << "Registered callback with handle" << handle;
    return handle;
}

void DiscoveryClient::unregisterCallback(int handle)
{
    m_callbacks.remove(handle);
    qDebug() << "Unregistered callback with handle" << handle;
}


// LibUV 事件循环
void DiscoveryClient::runLoop()
{
    qDebug() << "LibUV loop thread started";

    while (m_isRunning.load()) {
        int r = uv_run(m_loop, UV_RUN_ONCE);
        if (r == 0 && !m_isRunning.load()) {
            break;
        }

        // 检查超时
        auto current_time = std::chrono::steady_clock::now();
        auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(current_time - m_startTime).count();
        if (elapsed >= m_timeoutSeconds) {
            qDebug() << "Discovery timeout after" << m_timeoutSeconds << "seconds";
            m_isRunning.store(false);
            // 使用QMetaObject::invokeMethod确保信号在主线程中发出
            QMetaObject::invokeMethod(this, [this]() { 
                qDebug() << "=== Emitting discoveryFinished signal in main thread ===";
                emit discoveryFinished(); 
            }, Qt::QueuedConnection);
            break;
        }
    }

    qDebug() << "LibUV loop stopping...";
    stopLoopHandles();
    uv_run(m_loop, UV_RUN_NOWAIT);
    qDebug() << "LibUV loop thread finished";
}

void DiscoveryClient::stopLoopHandles()
{
    if (!m_loop)
        return;

    if (uv_is_active((uv_handle_t *)&m_udpHandle)) {
        // 离开多播组
        const char* multicastInterface = m_networkInterface.toUtf8().constData();
        int r = uv_udp_set_membership(&m_udpHandle, MULTICAST_ADDR.toUtf8().constData(), 
                                      multicastInterface, UV_LEAVE_GROUP);
        if (r != 0) {
            qDebug() << "Could not leave multicast group (this is usually harmless):" 
                     << MULTICAST_ADDR << "on interface:" << multicastInterface
                     << uv_strerror(r);
        } else {
            qDebug() << "Left multicast group:" << MULTICAST_ADDR
                     << "on interface:" << multicastInterface;
        }
        
        r = uv_udp_recv_stop(&m_udpHandle);
        if (r != 0) {
            qWarning() << "Failed to stop UDP recv:" << uv_strerror(r);
        }
        uv_close((uv_handle_t *)&m_udpHandle, nullptr);
    }

    // 停止并关闭重试定时器（如果已启动）
    if (uv_is_active(reinterpret_cast<uv_handle_t*>(&m_retryTimer))) {
        int r = uv_timer_stop(&m_retryTimer);
        if (r != 0) {
            qWarning() << "Failed to stop retry timer:" << uv_strerror(r);
        }
        uv_close(reinterpret_cast<uv_handle_t*>(&m_retryTimer), nullptr);
    }
}

void DiscoveryClient::sendDiscoveryRequest()
{
    if (!m_isRunning.load()) {
        qWarning() << "Cannot send discovery request: client not running";
        return;
    }

    qDebug() << "=== Sending Discovery Request ===" ;
    QString request = buildDiscoveryRequest();
    QByteArray requestData = request.toUtf8();
    
    qDebug() << "Request size:" << requestData.size() << "bytes";
    qDebug() << "Request content:" << request;
    
    // 发送UDP多播消息
    uv_buf_t send_buf = uv_buf_init((char *)requestData.constData(), requestData.size());
    uv_udp_send_t *send_req = new uv_udp_send_t;
    if (!send_req) {
        qCritical() << "Failed to allocate uv_udp_send_t";
        return;
    }

    int r = uv_udp_send(send_req, &m_udpHandle, &send_buf, 1, 
                       (const struct sockaddr *)&m_sendAddr, onUdpSend);
    if (r != 0) {
        qCritical() << "Failed to send discovery request:" << uv_strerror(r);
        delete send_req;
    } else {
        ++m_sentCount;
        qDebug() << "Discovery request sent to" << MULTICAST_ADDR << ":" << DISCOVERY_PORT;
        qDebug() << "Waiting for UDP send callback and potential responses...";
    }
}

// LibUV 静态回调函数
void DiscoveryClient::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
    Q_UNUSED(handle)
    size_t buffer_size = suggested_size > 0 ? suggested_size : 65536;
    char *buffer = new char[buffer_size];
    if (!buffer) {
        static char emergency_buffer[1];
        buf->base = emergency_buffer;
        buf->len = 0;
        qCritical() << "Memory allocation failed in onAllocBuffer";
        return;
    }
    buf->base = buffer;
    buf->len = buffer_size;
}

void DiscoveryClient::onUdpRecv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, 
                               const struct sockaddr* addr, unsigned flags)
{
    Q_UNUSED(flags)
    std::unique_ptr<char[]> buffer_guard(buf->base);
    
    DiscoveryClient *self = static_cast<DiscoveryClient *>(handle->data);
    if (self) {
        self->handleUdpRecv(nread, buf, addr, flags);
    }
}

void DiscoveryClient::onUdpSend(uv_udp_send_t* req, int status)
{
    if (status) {
        qCritical() << "UDP send error:" << uv_strerror(status);
    } else {
        qDebug() << "UDP send successful";
    }
    delete req;
}

void DiscoveryClient::walkCallback(uv_handle_t* handle, void* arg)
{
    Q_UNUSED(arg)
    if (!uv_is_closing(handle)) {
        qDebug() << "Closing handle during walk: type" << handle->type;
        uv_close(handle, nullptr);
    }
}

// 实例方法回调
void DiscoveryClient::handleUdpRecv(ssize_t nread, const uv_buf_t* buf, 
                                   const struct sockaddr* addr, unsigned flags)
{
    Q_UNUSED(flags)
    if (nread < 0) {
        qWarning() << "UDP receive error:" << uv_strerror(nread);
        return;
    }

    if (nread == 0) {
        return;
    }

    if (addr == nullptr) {
        qWarning() << "Received UDP packet with no sender address";
        return;
    }

    // 获取发送者信息
    char sender_ip[17] = {0};
    uv_ip4_name((const struct sockaddr_in *)addr, sender_ip, 16);
    int sender_port = ntohs(((const struct sockaddr_in *)addr)->sin_port);

    // 解析收到的原始数据
    QByteArray raw_data(buf->base, nread);
    qDebug() << "=== UDP Data Received ===" ;
    qDebug() << "Received" << nread << "bytes from" << sender_ip << ":" << sender_port;
    qDebug() << "Raw data:" << raw_data;

    parseDiscoveryResponse(raw_data, QString::fromUtf8(sender_ip), sender_port);
}

void DiscoveryClient::parseDiscoveryResponse(const QByteArray& data, const QString& senderIP, int senderPort)
{
    QString rawData = QString::fromUtf8(data);
    qDebug() << "=== Parsing discovery response ===";
    qDebug() << "From:" << senderIP << ":" << senderPort;
    qDebug() << "Data size:" << data.size() << "bytes";
    qDebug() << "Raw data:" << rawData;
    
    QString headers;
    QString body;
    
    if (!parseHttpResponse(rawData, headers, body)) {
        qWarning() << "Failed to parse HTTP response from" << senderIP;
        return;
    }

    // 检查是否是HTTP 200响应
    if (!headers.contains("HTTP/1.1 200")) {
        qWarning() << "Received non-200 response from" << senderIP;
        qDebug() << "Headers:" << headers;
        
        // 如果是我们自己发送的请求（环回测试），这是正常的
        if (headers.contains("POST /discovery HTTP/1.1")) {
            qDebug() << "Received our own multicast request (loopback test successful)";
            return;
        }
        return;
    }

    // 解析JSON-RPC响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(body.toUtf8(), &parseError);
    
    if (parseError.error != QJsonParseError::NoError) {
        qWarning() << "JSON parse error:" << parseError.errorString();
        return;
    }

    QJsonObject response = doc.object();
    
    // 检查是否包含错误信息
    if (response.contains("error")) {
        QJsonObject error = response["error"].toObject();
        qWarning() << "JSON-RPC error from" << senderIP << ":"
                   << "Code:" << error["code"].toInt()
                   << "Message:" << error["message"].toString();
        return;
    }
    
    if (!response.contains("result")) {
        qWarning() << "Invalid JSON-RPC response: missing result from" << senderIP;
        qDebug() << "Response body:" << body;
        return;
    }

    QJsonObject result = response["result"].toObject();
    
    // 验证必要字段是否存在
    if (result.isEmpty()) {
        qWarning() << "Empty result object from" << senderIP;
        return;
    }
    
    // 解析设备信息
    DeviceDiscoveryInfo device;
    device.ipAddress = senderIP;
    device.port = senderPort;
    
    // 根据服务端实际返回的字段解析
    device.deviceType = result["model"].toString("Unknown Device");  // 使用model作为设备类型
    device.manufacturer = result["manufacturer"].toString("Unknown Manufacturer");
    device.model = result["model"].toString("Unknown Model");
    device.status = "Active";
    
    // 检查网络信息
    QJsonObject network = result["network"].toObject();
    if (!network.isEmpty()) {
        QString deviceIP = network["ip"].toString();
        if (!deviceIP.isEmpty()) {
            device.ipAddress = deviceIP;  // 使用设备自报的IP地址
        }
    }
    
    // 构建标准的RTSP URL格式和Web接口
    device.webInterface = QString("http://%1").arg(device.ipAddress);
    // 生成标准RTSP URL：rtsp://IP:554/live/通道号/码流类型
    // 默认通道1，主码流(0)
    device.rtspUrl = QString("rtsp://%1:554/live/1/0").arg(device.ipAddress);
    
    device.additionalInfo = result;

    // 在单次扫描中按 IP 做一次简单去重，避免同一台设备多次统计
    if (m_seenDeviceIps.contains(device.ipAddress)) {
        qDebug() << "Duplicate discovery for IP" << device.ipAddress << ", ignoring for this scan";
        return;
    }
    m_seenDeviceIps.insert(device.ipAddress);
    
    qDebug() << "Device discovered successfully:"
             << "Type:" << device.deviceType
             << "Manufacturer:" << device.manufacturer 
             << "Model:" << device.model
             << "IP:" << device.ipAddress
             << "Port:" << device.port;

    // 通知所有注册的回调
    for (auto it = m_callbacks.begin(); it != m_callbacks.end(); ++it) {
        if (it.value()) {
            it.value()(device);
        }
    }

    // 使用QMetaObject::invokeMethod确保信号在主线程中发出
    QMetaObject::invokeMethod(this, [this, device]() {
        qDebug() << "=== Emitting deviceFound signal in main thread ===";
        emit deviceFound(device);
    }, Qt::QueuedConnection);
}

QString DiscoveryClient::buildDiscoveryRequest()
{
    // 生成唯一ID
    QString id = QString("discovery-%1").arg(QRandomGenerator::global()->generate());
    QString method = "discovery.search";
    QJsonObject params;
    params["client_id"] = "qt_discovery_client_libuv";
    params["filters"] = QJsonObject();

    QString requestBody = createJsonRpcRequest(id, method, params);

    // 构造HTTP请求
    QString httpRequest = QString(
        "POST /discovery HTTP/1.1\r\n"
        "Host: %1:%2\r\n"
        "Content-Type: application/json\r\n"
        "Content-Length: %3\r\n"
        "Connection: close\r\n"
        "\r\n%4")
        .arg(MULTICAST_ADDR)
        .arg(DISCOVERY_PORT)
        .arg(requestBody.toUtf8().size())
        .arg(requestBody);

    return httpRequest;
}

QString DiscoveryClient::createJsonRpcRequest(const QString& id, const QString& method, const QJsonObject& params)
{
    QJsonObject request;
    request["jsonrpc"] = "2.0";
    request["id"] = id;
    request["method"] = method;
    request["params"] = params;

    QJsonDocument doc(request);
    return doc.toJson(QJsonDocument::Compact);
}

bool DiscoveryClient::parseHttpResponse(const QString& rawData, QString& headers, QString& body)
{
    // 查找HTTP头部和消息体的分隔符
    int headerEndPos = rawData.indexOf("\r\n\r\n");
    
    if (headerEndPos != -1) {
        headers = rawData.left(headerEndPos);
        body = rawData.mid(headerEndPos + 4);
        qDebug() << "HTTP Headers:" << headers;
        qDebug() << "HTTP Body:" << body;
        return true;
    } else {
        // 尝试查找只有 \n\n 的分隔符（某些服务器可能不使用 \r\n）
        headerEndPos = rawData.indexOf("\n\n");
        if (headerEndPos != -1) {
            headers = rawData.left(headerEndPos);
            body = rawData.mid(headerEndPos + 2);
            qDebug() << "HTTP Headers (LF only):" << headers;
            qDebug() << "HTTP Body (LF only):" << body;
            return true;
        } else {
            // 没有找到HTTP头部，可能是纯消息体
            qWarning() << "No HTTP headers found, treating as raw message body";
            headers = "";
            body = rawData;
            return false;
        }
    }
}

} // namespace Discovery